﻿' ----------------------------------------------------------------------------------
' Microsoft Developer & Platform Evangelism
' 
' Copyright (c) Microsoft Corporation. All rights reserved.
' 
' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
' OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ----------------------------------------------------------------------------------
' The example companies, organizations, products, domain names,
' e-mail addresses, logos, people, places, and events depicted
' herein are fictitious.  No association with any real company,
' organization, product, domain name, email address, logo, person,
' places, or events is intended or should be inferred.
' ----------------------------------------------------------------------------------

Imports System.Globalization
Imports System.Net
Imports System.ServiceModel
Imports System.ServiceModel.Activation
Imports System.ServiceModel.Web
Imports Microsoft.Samples.WindowsPhoneCloud.Web.Infrastructure
Imports Microsoft.Samples.WindowsPhoneCloud.Web.Models
Imports Microsoft.Samples.WindowsPhoneCloud.Web.UserAccountWrappers

Namespace Services
    <ServiceBehavior(IncludeExceptionDetailInFaults:=False), AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
    Public Class AuthenticationService
        Implements IAuthenticationService
        Private ReadOnly formsAuth As IFormsAuthentication
        Private ReadOnly membershipService As IMembershipService
        Private ReadOnly userPrivilegesRepository As IUserPrivilegesRepository

        Public Sub New()
            Me.New(New FormsAuthenticationService(), New AccountMembershipService(), New UserTablesServiceContext())
        End Sub

        <CLSCompliant(False)>
        Public Sub New(ByVal formsAuth As IFormsAuthentication, ByVal membershipService As IMembershipService, ByVal userPrivilegesRepository As IUserPrivilegesRepository)
            If formsAuth Is Nothing Then
                Throw New ArgumentNullException("formsAuth", "The Forms Authentication service cannot be null.")
            End If

            If membershipService Is Nothing Then
                Throw New ArgumentNullException("membershipService", "The Membership service cannot be null.")
            End If

            If userPrivilegesRepository Is Nothing Then
                Throw New ArgumentNullException("userPrivilegesRepository", "The User Privileges Repository cannot be null.")
            End If

            Me.formsAuth = formsAuth
            Me.membershipService = membershipService
            Me.userPrivilegesRepository = userPrivilegesRepository
        End Sub

        Public Function GenerateAuthToken(ByVal login As Login) As String Implements IAuthenticationService.GenerateAuthToken
            If (login Is Nothing) OrElse String.IsNullOrEmpty(login.UserName) OrElse String.IsNullOrEmpty(login.Password) Then
                Throw New WebFaultException(Of String)("Invalid credentials.", HttpStatusCode.BadRequest)
            End If

            If Me.membershipService.ValidateUser(login.UserName, login.Password) Then
                Dim user = Me.membershipService.GetUser(login.UserName)
                Dim ticket = New FormsAuthenticationTicket(user.UserName, False, Integer.MaxValue)
                Dim token = Me.formsAuth.Encrypt(ticket)

                Return token
            End If

            Return String.Empty
        End Function

        Public Function ValidateAuthToken(ByVal token As String) As String Implements IAuthenticationService.ValidateAuthToken
            If String.IsNullOrEmpty(token) Then
                Throw New WebFaultException(Of String)("Token cannot be null or empty.", HttpStatusCode.BadRequest)
            End If

            Dim ticket = Me.formsAuth.Decrypt(token)
            If ticket IsNot Nothing Then
                Return ticket.Name
            End If

            Return Nothing
        End Function

        Public Function CreateUser(ByVal user As RegistrationUser) As String Implements IAuthenticationService.CreateUser
            If (user Is Nothing) OrElse String.IsNullOrEmpty(user.Name) OrElse String.IsNullOrEmpty(user.EMail) OrElse String.IsNullOrEmpty(user.Password) Then
                Throw New WebFaultException(Of String)("Invalid user information.", HttpStatusCode.BadRequest)
            End If

            Dim createStatus = Me.membershipService.CreateUser(user.Name, user.Password, user.EMail)
            If createStatus.Equals(MembershipCreateStatus.Success) Then
                Me.SetUserDefaultPermissions(Me.membershipService.GetUser(user.Name).ProviderUserKey.ToString())
            End If

            Return createStatus.ToString()
        End Function

        Private Sub SetUserDefaultPermissions(ByVal userId As String)
            Me.userPrivilegesRepository.AddPrivilegeToUser(userId, PrivilegeConstants.TablesUsagePrivilege)
            Me.userPrivilegesRepository.AddPrivilegeToUser(userId, PrivilegeConstants.BlobsUsagePrivilege)
            Me.userPrivilegesRepository.AddPrivilegeToUser(userId, PrivilegeConstants.QueuesUsagePrivilege)
            Me.userPrivilegesRepository.AddPrivilegeToUser(userId, PrivilegeConstants.SqlUsagePrivilege)
            Me.userPrivilegesRepository.AddPrivilegeToUser(userId, String.Format(CultureInfo.InvariantCulture, "{0}{1}", "SampleData", PrivilegeConstants.TablePrivilegeSuffix))
        End Sub
    End Class
End Namespace